package cn.shanguoyu.base.springboot.starter.idempotent.core.strategy.impl.token;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import cn.shanguoyu.base.springboot.starter.cache.abs.Cache;
import cn.shanguoyu.base.springboot.starter.convention.errorcode.ClientErrorCode;
import cn.shanguoyu.base.springboot.starter.convention.exception.ClientException;
import cn.shanguoyu.base.springboot.starter.idempotent.core.IdempotentParamWrapper;
import cn.shanguoyu.base.springboot.starter.idempotent.core.strategy.abs.AbstractIdempotentTemplate;
import cn.shanguoyu.base.springboot.starter.web.toolkit.MvcUtil;
import lombok.RequiredArgsConstructor;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * @description:
 * @author：sgy
 * @date: 2023-06-03
 */
@RequiredArgsConstructor
public class IdempotentTokenExecuteHandler extends AbstractIdempotentTemplate implements IdempotentTokenService {
    private final Cache cache;
    private final IdempotentTokenProperties idempotentTokenProperties;
    private static final String TOKEN_KEY = "idempotent-token";
    private static final String TOKEN_PREFIX_KEY = "idempotent:token:{}";

    @Override
    protected void buildWrapper(IdempotentParamWrapper idempotentParamWrapper) {

    }

    @Override
    protected void handler(IdempotentParamWrapper wrapper) {
        HttpServletRequest request = MvcUtil.getHttpRequest();
        String reqToken = request.getHeader(TOKEN_KEY);
        // 如果请求头没有Token则抛出异常
        if (StrUtil.isBlank(reqToken)) {
            throw new ClientException(ClientErrorCode.IDEMPOTENT_TOKEN_NULL_ERROR);
        }
        // 如果有Token则删除缓存的Token
        Boolean tokenDeleteFlag = cache.delete(reqToken);
        // 如果删除失败了，有两种情况：Token不正确，Token过期了
        if (!tokenDeleteFlag) {
            String errMsg = StrUtil.isNotBlank(wrapper.getIdempotent().message())
                    ? wrapper.getIdempotent().message()
                    : ClientErrorCode.IDEMPOTENT_TOKEN_DELETE_ERROR.message();
            throw new ClientException(errMsg, ClientErrorCode.IDEMPOTENT_TOKEN_DELETE_ERROR);
        }
    }

    @Override
    public String createToken() {
        String token = buildToken();
        cache.strPut(token, "", idempotentTokenProperties.getTimeout(), TimeUnit.SECONDS);
        return token;
    }

    /**
     * 根据配置的前缀或者默认的前缀生成缓存的key
     *
     * @return
     */
    private String buildToken() {
        String token = null;
        if (StrUtil.isNotBlank(idempotentTokenProperties.getPrefix())) {
            String template = StrUtil.join(idempotentTokenProperties.getPrefix(), StrPool.COLON, TOKEN_PREFIX_KEY);
            token = StrUtil.format(template, UUID.fastUUID().toString());
        } else {
            token = StrUtil.format(TOKEN_PREFIX_KEY, UUID.fastUUID().toString());
        }
        return token;
    }
}
